<template>
  <div ref="canvas"></div>
</template>

<script lang="ts" setup>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
import { ref, onMounted } from "vue";

// 画布
const canvas = ref<any>('');
// 场景
const scene = new THREE.Scene();
// 材质
const material = new THREE.MeshLambertMaterial({
  color: 0xff0000, // 颜色
  side: THREE.DoubleSide, // 双面可见
});
// 几何图形
const geometry = new THREE.BoxGeometry(100, 100, 100);
// 网格模型Mesh
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// 多个Mesh共享几何体与材质 - 修改一个另一个也会随之改变
const mesh2 = new THREE.Mesh(geometry, material);
mesh2.position.x = 200;
scene.add(mesh2);
// 两个mesh共享一个材质，改变一个mesh的颜色，另一个mesh2的颜色也会跟着改变
// mesh.material和mesh2.material都指向同一个material
// 三者等价：mesh.material、mesh2.material、material
mesh.material.color.set(0xffff00);
// 三者等价：mesh.geometry、mesh2.geometry、geometry
mesh.geometry.translate(0,100,0);

// 克隆几何体和材质则不会出现这种情况
// @ts-ignore
// mesh2.geometry = mesh.geometry.clone();
// mesh2.material = mesh.material.clone();

// 实例化一个gui对象 - 可视化改变三维场景
const gui = new GUI();
// 通过 GUI 改变 材质 颜色
gui.addColor(material, "color").name("材质颜色").onChange((val) => {
  console.log('材质 color onchange ', val);
});

// 光源
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambientLight);
// 相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 3000);
camera.position.set(400, 400, 400);
camera.lookAt(0, 0, 0);

// 欧拉对象和四元数主要用来表达对象的旋转信息 - Object3D对象角度属性.rotation的值是欧拉对象Euler
// 比如 mesh.rotation.x 这个 rotation 就是欧拉对象
// 创建一个欧拉对象，表示绕着xyz轴分别旋转45度，0度，90度
// const euler = new THREE.Euler( Math.PI / 4, 0, Math.PI / 2);

// 渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// 渲染函数
function render() {
  // 围绕某个轴旋转
  // const axis = new THREE.Vector3(0,1,0);
  // mesh.rotateOnAxis(axis,Math.PI / 100);

  mesh.rotateY(0.01);
  // 同步 mesh 的姿态角度属性给 mesh2 让两个几何体之间始终保持一致的姿势
  mesh2.rotation.copy(mesh.rotation);

  renderer.render(scene, camera);
  requestAnimationFrame(render);
}
// 相机控件
const orbitControl = new OrbitControls(camera, renderer.domElement);
orbitControl.update();

onMounted(() => {
  canvas.value.appendChild(renderer.domElement);
  render();
});

</script>
